package com.kgc.est.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kgc.est.constants.Constants;
import com.kgc.est.dto.*;
import com.kgc.est.mapper.*;
import com.kgc.est.pojo.*;
import com.kgc.est.utils.MathUtils;
import com.kgc.est.utils.Result;
import com.kgc.est.utils.ResultUtils;
import com.kgc.est.utils.StringUtil;
import com.kgc.est.utils.oss.OssConfig;
import com.kgc.est.utils.redis.RedisKeyUtils;
import com.kgc.est.utils.redis.RedisUtils;
import io.swagger.annotations.Api;
import netscape.security.ForbiddenTargetException;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.bouncycastle.cms.PasswordRecipientId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Transactional  //事务处理
@RestController
@RequestMapping("/evaluate")
public class EvaluateServiceImpl {

    Logger log = LoggerFactory.getLogger(EvaluateServiceImpl.class);

    @Autowired(required = false)
    private MalfunctionMapper malfunctionMapper;

    @Autowired(required = false)
    private MalfunctionOptionsMapper malfunctionOptionsMapper;

    @Autowired(required = false)
    private RedisUtils redisUtils;

    @Autowired(required = false)
    private EvaluateMapper evaluateMapper;

    @Autowired(required = false)
    private EvaluateDetailMapper evaluateDetailMapper;

    @Autowired(required = false)
    private ModelMapper modelMapper;

    @Autowired
    private OssConfig ossConfig;

    /**
     * 根据商品id查询故障列表
     *      1.根据商品类型id查询出故障大类信息
     *      2.遍历故障大类信息，然后根据故障大类id查询出对应的故障项目
     * @param modelId
     * @return
     */
    @GetMapping("/specList")
    Result specList(@RequestParam("modelId")Long modelId){
        log.info("服务提供者拿到的商品类型id：{}",modelId);

        //创建wrapper，添加查询条件
        QueryWrapper<Malfunction> qw = new QueryWrapper<Malfunction>();
        qw.eq("modelId",modelId);
        qw.eq("isDelete",0);

        List<Malfunction> malfunctions = malfunctionMapper.selectList(qw);

        List<MalfunctionDto> malfunctionDtos = new ArrayList<>();
        //遍历查询到的数据，然后转存到出参对象中
        for (Malfunction malfunction : malfunctions) {
            MalfunctionDto malfunctionDto = new MalfunctionDto();
            try {
                BeanUtils.copyProperties(malfunctionDto,malfunction);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

            //根据malfunction对象的id查询出故障项的信息
            QueryWrapper<MalfunctionOptions> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("malfId",malfunction.getId());
            queryWrapper.eq("isDelete",0);

            List<MalfunctionOptions> malfunctionOptions = malfunctionOptionsMapper.selectList(queryWrapper);

            List<MalfunctionOptionsDto> malfunctionOptionsDtos = new ArrayList<>();
            //遍历
            for (MalfunctionOptions malfunctionOption : malfunctionOptions) {
                MalfunctionOptionsDto malfunctionOptionsDto = new MalfunctionOptionsDto();
                try {
                    BeanUtils.copyProperties(malfunctionOptionsDto,malfunctionOption);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
                malfunctionOptionsDtos.add(malfunctionOptionsDto);

            }

            malfunctionDto.setOptionsList(malfunctionOptionsDtos);
            malfunctionDtos.add(malfunctionDto);
        }
        return ResultUtils.returnDataSuccess(malfunctionDtos);
    }


    /**
     * 1.创建一条用户维修的评估信息
     *      评估价格，以及定金价格，维修人员id
     *
     * 2.需要创建多条维修评估项信息
     * @param modelId
     * @param optionIds
     * @param token
     * @return
     */
    @GetMapping("/assess")
    public Result assess(@RequestParam("modelId") Long modelId,
                  @RequestParam("optionIds") String optionIds,
                  @RequestParam("token") String token){

        log.info("modelId:{},optionIds:{},token:{}",modelId,optionIds,token);
        //1.通过token获取用户的信息
        String value = redisUtils.getValue(RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_TOKEN,token));
        log.info("用户信息：{}",value);
        //如果没有用户信息，返回让用户去登录
        if (StringUtils.isBlank(value)){
            return ResultUtils.returnFail();
        }

        //得到登录用户信息
        Users users = JSON.parseObject(value, Users.class);

        //先把维修商品的总价格定义
        BigDecimal totalPrice = new BigDecimal(0);

        //计算价格，需要先把价格查询出来

        QueryWrapper<Malfunction> qw = new QueryWrapper<Malfunction>();
        qw.eq("modelId",modelId);
        qw.eq("isDelete",0);

        //查询出故障表中数据，可以得到故障大项的价格
        List<Malfunction> malfunctions = malfunctionMapper.selectList(qw);

        //把故障小项的id处理一下，从字符串转换成Long集合
        Set<Long> optionIdSet = StringUtil.string2LongSet(optionIds, Constants.Connnector.COMMA_);
        //遍历故障大项
        for (Malfunction malfunction : malfunctions) {
            //得到当前大项的维修价格
            BigDecimal maintainTopPrice = malfunction.getMaintainTopPrice();

            //查询用户选择的故障详情对象，拿到价格占比
            //迭代optionIdSet
            for (Long optionId : optionIdSet) {
                //拿到维修故障小项
                MalfunctionOptions malfunctionOptions = malfunctionOptionsMapper.selectById(optionId);
                Integer ratio = malfunctionOptions.getRatio();  //获取价格占比

                //判断
                if (malfunction.getId()==malfunctionOptions.getMalfId()){
                    //计算此项故障维修需要的金额 = 总金额 * 占比（百分比）
                    BigDecimal price = totalPrice.add(maintainTopPrice.multiply(new BigDecimal(ratio)))
                            .multiply(new BigDecimal(Constants.ProcessType.RATIO));
                    //把计算当前项的金额添加到总金额中 totalPrice += price
                    log.info("{}的维修金额是：{}",malfunctionOptions.getOptionName(),price);
                    totalPrice = totalPrice.add(price);
                    break;
                }

            }

        }//循环结束，该商品的总维修金额就计算出来了
        //格式化总价格  保留2位小数
        totalPrice = MathUtils.formatDecimal(totalPrice,Constants.DECIMAL_DIGITS);
        //计算定金
        BigDecimal subscription = totalPrice.multiply(new BigDecimal(Constants.Order.Subscription.RATIO));

        //保存评估信息
        Evaluate evaluate = new Evaluate();
        evaluate.setModelId(modelId);
        evaluate.setPrice(totalPrice);
        evaluate.setSubscription(subscription);
        evaluate.setCreatedUserId(users.getId());
        //把评估信息保存到数据库中
        evaluateMapper.insert(evaluate);

        //保存商品维修评估详情
        addMalfunctionOptions(evaluate.getId(),optionIdSet,users.getId());

        EvaluateDto evaluateDto = new EvaluateDto(evaluate);

        return ResultUtils.returnDataSuccess(evaluateDto);
    }


    /**
     *根据评估ID查询 评估对象（一条）
     *      然后查询商品对象（一条）
     *      查询评估详情对象（多条）
     * @param id
     * @return
     */
    @GetMapping("/{id}/assessInfo")
    public Result assessInfo(@PathVariable("id") Long id){
        //1.查询评估对象
        Evaluate evaluate = evaluateMapper.selectById(id);

        //把对象信息存储到出参dto中
        EvaluateDto evaluateDto = new EvaluateDto(evaluate);

        //2.查询商品对象
        Model model = modelMapper.selectById(evaluate.getModelId());

        //把model对象中的信息转移到modelDto中
        ModelDto modelDto = new ModelDto(model);
        modelDto.setFaceImg(ossConfig.getOssWebUrl()+model.getFaceImg());
        modelDto.setContentImg(ossConfig.getOssWebUrl()+model.getContentImg());
        evaluateDto.setModel(modelDto);

        //3.查询评估详情集合
        QueryWrapper<EvaluateDetail> qw = new QueryWrapper<>();
        //拼接查询条件
        qw.eq("evaluateId",evaluate.getId());
        List<EvaluateDetail> evaluateDetails = evaluateDetailMapper.selectList(qw);

        ArrayList<EvaluateDetailDto> evaluateDetailDtos = new ArrayList<>();

        for (EvaluateDetail evaluateDetail : evaluateDetails) {
            EvaluateDetailDto evaluateDetailDto = new EvaluateDetailDto();
            try {
                BeanUtils.copyProperties(evaluateDetailDto,evaluateDetail);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            evaluateDetailDtos.add(evaluateDetailDto);
        }
        evaluateDto.setDetailList(evaluateDetailDtos);

        return ResultUtils.returnDataSuccess(evaluateDto);
    }



    private void addMalfunctionOptions(Long evaluateId,Set<Long> optionIdSet,Long userId){
        for (Long optionId : optionIdSet) {
            MalfunctionOptions malfunctionOptions = malfunctionOptionsMapper.selectById(optionId);
            EvaluateDetail detail = new EvaluateDetail();
            detail.setEvaluateId(evaluateId);
            detail.setMalfId(malfunctionOptions.getMalfId());
            detail.setOptionId(malfunctionOptions.getId());
            detail.setOptionName(malfunctionOptions.getOptionName());
            detail.setCreatedUserId(userId);
            evaluateDetailMapper.insert(detail);
        }
    }

}
